package com.winchain.chainbill.bill.biz.receive.service.impl;

import com.shell.bee.acct.account.po.AcctBas;
import com.shell.bee.base.utils.DateUtil;
import com.shell.bee.base.utils.StringUtil;
import com.shell.bee.base.utils.SystemUtil;
import com.winchain.basic.exception.ExtException;
import com.winchain.chainbill.bill.base.po.CbCert;
import com.winchain.chainbill.bill.base.po.CbDct;
import com.winchain.chainbill.bill.base.po.CbHldr;
import com.winchain.chainbill.bill.base.po.CbOpt;
import com.winchain.chainbill.bill.base.po.CbRcv;
import com.winchain.chainbill.bill.base.po.CbRec;
import com.winchain.chainbill.bill.base.po.CbRpur;
import com.winchain.chainbill.bill.base.po.CbSnd;
import com.winchain.chainbill.bill.base.po.CbXfe;
import com.winchain.chainbill.bill.base.service.CbCertService;
import com.winchain.chainbill.bill.base.service.CbDctService;
import com.winchain.chainbill.bill.base.service.CbHldrService;
import com.winchain.chainbill.bill.base.service.CbRcvService;
import com.winchain.chainbill.bill.base.service.CbRecService;
import com.winchain.chainbill.bill.base.service.CbSndService;
import com.winchain.chainbill.bill.base.service.CbXfeService;
import com.winchain.chainbill.bill.biz.receive.service.BillCertService;
import com.winchain.chainbill.trade.service.BillAcctService;
import com.winchain.provider.expiration.service.BillExpHldrService;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service("billCertService")
public class BillCertServiceImpl implements BillCertService {
	@Autowired
	private CbCertService cbCertService;
	@Autowired
	private CbSndService cbSndService;
	@Autowired
	private CbRcvService cbRcvService;
	@Autowired
	private CbXfeService cbXfeService;
	@Autowired
	private BillAcctService billAcctService;
	@Autowired
	private CbRecService cbRecService;
	@Autowired
	private CbHldrService cbHldrService;
	@Autowired
	private CbDctService cbDctService;
	@Autowired
	private BillExpHldrService billExpHldrService;

	public void certXfeRej(CbRec cbRec, CbRcv cbRcv) {
		CbCert cert = initCert(cbRec, cbRcv);
		cert.setEntId(cbRcv.getBuyerId());
		cert.setBizId(cbRcv.getRcvId());
		cert.setCertType("0");
		this.cbCertService.save(cert);
	}

	public void cert(CbRec cbRec, CbRcv cbRcv) {
		CbCert cert = initCert(cbRec, cbRcv);
		cert.setEntId(cbRcv.getBuyerId());
		if ("0".equals(cbRcv.getTxType())) {
			cert.setCertType("0");
			cert.setBizId(cbRcv.getRcvId());
		} else {
			CbXfe cbXfe = getXfe(cbRec, cbRcv);
			if ((cbXfe.getPrntId() == null) || (cbXfe.getBillId().equals(cbXfe.getPrntId()))) {
				cert.setCertType("2");
			} else {
				cert.setCertType("4");
				initPrnt(cert, cbRec.getPrntId());
				cert.setSplitDate(DateUtil.getSystemDate());
			}
			cert.setBizId(cbXfe.getXfeId());
			cert.setXfeDate(DateUtil.getSystemDate());
			cert.setXfeNm(cbXfe.getBuyerNm());
		}
		this.cbCertService.save(cert);

		cert = initCert(cbRec, cbRcv);
		cert.setEntId(cbRcv.getSellerId());
		if ("0".equals(cbRcv.getTxType())) {
			cert.setCertType("1");
			cert.setBizId(cbRcv.getRcvId());
		} else {
			CbXfe cbXfe = getXfe(cbRec, cbRcv);
			if (cbXfe.getBillId().equals(cbXfe.getPrntId())) {
				cert.setCertType("3");
			} else {
				cert.setCertType("5");
				cert.setPrntId(cbXfe.getPrntId());
				cert.setSplitDate(DateUtil.getSystemDate());
			}
			cert.setBizId(cbXfe.getXfeId());
			cert.setXfeDate(DateUtil.getSystemDate());
			cert.setXfeNm(cbXfe.getBuyerNm());
		}
		this.cbCertService.save(cert);
	}

	private CbCert initCert(CbRec cbRec, CbRcv cbRcv) {
		CbCert cert = new CbCert();

		cert.setCertId(SystemUtil.getUUID());
		cert.setCertDate(DateUtil.getSystemDate());
		cert.setCreateTime(DateUtil.getSystemDateTime());

		initRec(cert, cbRec);
		initSnd(cert, cbRec.getRootId());
		initHldr(cert, cbRcv.getSellerId());
		initFin(cert, cbRec.getRootId());

		return cert;
	}

	private void initDct(CbCert cert, CbDct cbDct) {
		String prntId = cbDct.getPrntId();
		CbRec cbRec = (CbRec) this.cbRecService.selectByKey(prntId);
		cert.setPrntId(prntId);
		cert.setPrntCode(cbRec.getBillCode());
		cert.setSplitDate(cbDct.getCreateTime());
	}

	private void initXfe(CbCert cert, CbXfe cbXfe) {
		String prntId = cbXfe.getPrntId();
		CbRec cbRec = (CbRec) this.cbRecService.selectByKey(prntId);
		cert.setPrntId(prntId);
		cert.setPrntCode(cbRec.getBillCode());
		cert.setSplitDate(cbXfe.getCreateTime());
	}

	private void initRec(CbCert cert, CbRec cbRec) {
		cert.setBillId(cbRec.getBillId());
		cert.setBillCode(cbRec.getBillCode());
		cert.setBillAmt(cbRec.getBillAmt());

		cert.setOptSeq(cbRec.getOptSeq());
		cert.setPmtDate(cbRec.getExpDate());
		cert.setStateNm(cbRec.getBillState());
		cert.setExpDate(cbRec.getExpDate());
		cert.setSndDate(cbRec.getSndDate());
		cert.setConfirmerId(cbRec.getConfirmerId());
		cert.setConfirmerNm(cbRec.getConfirmerNm());
		if ((StringUtil.empty(cbRec.getConfirmerId())) || (StringUtil.empty(cbRec.getConfirmerNm()))) {
			CbRec bill = (CbRec) this.cbRecService.selectByKey(cbRec.getBillId());
			cert.setConfirmerId(bill.getConfirmerId());
			cert.setConfirmerNm(bill.getConfirmerNm());
		}
	}

	private void initSnd(CbCert cert, String rootId) {
		CbSnd cbSnd = new CbSnd();
		cbSnd.setBillId(rootId);
		cbSnd = (CbSnd) this.cbSndService.selectOne(cbSnd);

		AcctBas acct = this.billAcctService.getAcctBas(cbSnd.getBuyerId(), null, "00");
		cert.setSndId(acct.getCustId());
		cert.setSndNm(acct.getCustNm());
		cert.setSndAcct(acct.getAcctNo());
		cert.setSndTxNo(acct.getFiNm());
	}

	private void initHldr(CbCert cert, String hldrId) {
		AcctBas acct = this.billAcctService.getAcctBas(hldrId, null, "00");
		if (acct == null) {
			throw new ExtException("����[" + hldrId + "]��������������");
		}
		cert.setHldrId(acct.getCustId());
		cert.setHldrNm(acct.getCustNm());
		cert.setHldrAcct(acct.getAcctNo());
		cert.setHldrTxNo(acct.getFiNm());
	}

	private void initFin(CbCert cert, String billId) {
		CbRec cbRec = (CbRec) this.cbRecService.selectByKey(billId);

		cert.setFinId(cbRec.getFinId());
		cert.setFinNm(cbRec.getFinNm());
	}

	private void initPrnt(CbCert cert, String billId) {
		CbRec pCbRec = (CbRec) this.cbRecService.selectByKey(billId);
		cert.setPrntId(pCbRec.getBillId());
		cert.setPrntCode(pCbRec.getBillCode());
	}

	public void certForKeep(CbRec cbRec, CbXfe cbXfe) {
		CbCert cert = new CbCert();

		cert.setCertId(SystemUtil.getUUID());
		cert.setCertDate(DateUtil.getSystemDate());
		cert.setCreateTime(DateUtil.getSystemDateTime());

		cert.setBizId(cbRec.getBillId());
		initRec(cert, cbRec);
		initSnd(cert, cbRec.getRootId());
		initFin(cert, cbRec.getRootId());
		initXfe(cert, cbXfe);

		cert.setCertType("6");

		CbRcv cbRcv = new CbRcv();
		cbRcv.setBillId(cbRec.getBillId());
		cbRcv.setRcvState("2");

		cbRcv = (CbRcv) this.cbRcvService.selectOne(cbRcv);

		initHldr(cert, cbRcv.getSellerId());
		cert.setEntId(cbRcv.getSellerId());

		this.cbCertService.save(cert);

		CbCert prntCert = new CbCert();
		BeanUtils.copyProperties(cert, prntCert);
		prntCert.setCertId(SystemUtil.getUUID());
		prntCert.setBillId(cbRec.getPrntId());
		this.cbCertService.save(prntCert);
	}

	public void certForKeep(CbRec cbRec, CbDct cbDct) {
		CbCert cert = new CbCert();

		cert.setCertId(SystemUtil.getUUID());
		cert.setCertDate(DateUtil.getSystemDate());
		cert.setCreateTime(DateUtil.getSystemDateTime());

		cert.setBizId(cbRec.getBillId());
		initRec(cert, cbRec);
		initSnd(cert, cbRec.getRootId());
		initFin(cert, cbRec.getRootId());
		initDct(cert, cbDct);

		cert.setCertType("6");

		CbRcv cbRcv = new CbRcv();
		cbRcv.setBillId(cbRec.getBillId());
		cbRcv.setRcvState("2");

		cbRcv = (CbRcv) this.cbRcvService.selectOne(cbRcv);

		initHldr(cert, cbRcv.getSellerId());
		cert.setEntId(cbRcv.getSellerId());

		this.cbCertService.save(cert);

		CbCert prntCert = new CbCert();
		BeanUtils.copyProperties(cert, prntCert);
		prntCert.setCertId(SystemUtil.getUUID());
		prntCert.setBillId(cbRec.getPrntId());
		this.cbCertService.save(prntCert);
	}

	public void cert(CbRec cbRec, CbDct cbDct) {
		CbCert cert = new CbCert();

		cert.setCertId(SystemUtil.getUUID());
		cert.setCertDate(DateUtil.getSystemDate());
		cert.setCreateTime(DateUtil.getSystemDateTime());

		cert.setBizId(cbDct.getDctId());

		initHldrForFin(cert, cbDct.getFinId());

		initRec(cert, cbRec);
		initSnd(cert, cbRec.getRootId());

		cert.setDctDate(cbDct.getDctDate());

		cert.setDctRate(cbDct.getFixedRate().add(cbDct.getVarRate()));
		cert.setDctDays(cbDct.getDctDays());
		cert.setDctInt(cbDct.getDctInt());
		cert.setFinId(cbDct.getFinId());
		cert.setFinNm(cbDct.getFinNm());
		cert.setFinTxNo(cbDct.getFinAcct());

		cert.setEntId(cbDct.getSellerId());
		if ((cbDct.getPrntId() == null) || (cbDct.getBillId().equals(cbDct.getPrntId()))) {
			cert.setCertType("7");
			this.cbCertService.save(cert);
		} else {
			cert.setCertType("8");
			initPrnt(cert, cbRec.getPrntId());
			this.cbCertService.save(cert);

			CbCert prntCert = new CbCert();
			BeanUtils.copyProperties(cert, prntCert);
			prntCert.setCertId(SystemUtil.getUUID());
			prntCert.setBillId(cbRec.getPrntId());
			this.cbCertService.save(prntCert);
		}
	}

	private void initHldrForFin(CbCert cert, String hldrId) {
		AcctBas acct = this.billAcctService.getAcctBas(hldrId, null, "00");
		cert.setHldrId(acct.getCustId());
		cert.setHldrNm(acct.getCustNm());
		cert.setHldrAcct(acct.getAcctNo());
		cert.setHldrTxNo(acct.getFiNm());
	}

	public void cert(CbRec cbRec, CbRpur cbRpur) {
		CbCert cert = new CbCert();

		cert.setCertId(SystemUtil.getUUID());
		cert.setCertDate(DateUtil.getSystemDate());
		cert.setCreateTime(DateUtil.getSystemDateTime());

		cert.setBizId(cbRpur.getRpurId());
		initHldr(cert, cbRpur.getBuyerId());

		initRec(cert, cbRec);
		initSnd(cert, cbRec.getRootId());
		initFin(cert, cbRec.getBillId());
		cert.setRpurAmt(cbRpur.getRpurAmt().subtract(cbRpur.getRpurInt()));
		cert.setRpurDate(cbRpur.getRpurDate());
		cert.setRpurNm(cbRpur.getBuyerNm());
		cert.setRpurId(cbRpur.getBuyerId());
		cert.setRpurRate(cbRpur.getFixedRate().add(cbRpur.getVarRate()));

		cert.setEntId(cbRpur.getBuyerId());

		cert.setCertType("9");

		this.cbCertService.save(cert);
	}

	public void certForExp(CbRec rec, CbOpt operation) {
		String billId = rec.getBillId();
		String prntId = rec.getPrntId();
		String curState = operation.getCurState();

		CbHldr hldr = this.billExpHldrService.getHldrWithNewTx(billId, rec.getHldrLvl().intValue());
		String hldrId = hldr.getHldrId();

		CbCert cert = initExpCert(rec, hldr);
		if (prntId == null) {
			cert.setCertType("10");
			cert.setEntId(cert.getSndId());
			this.cbCertService.save(cert);
		}
		if (("S005".equals(curState)) || ("S011".equals(curState)) || ("S012".equals(curState))) {
			cert.setCertId(SystemUtil.getUUID());
			String entId = hldrId;
			cert.setEntId(entId);
			if (StringUtil.emptyAndNull(prntId)) {
				CbXfe xfe = new CbXfe();
				xfe.setBillId(billId);
				xfe.setXfeState("2");
				xfe = (CbXfe) this.cbXfeService.selectOne(xfe);
				if (xfe == null) {
					cert.setCertType("10");
					this.cbCertService.save(cert);
				} else {
					cert.setCertType("13");
					setExpXfe(cert, rec, hldr, null, false);
					this.cbCertService.save(cert);
				}
			} else {
				CbRec prntRec = (CbRec) this.cbRecService.selectByKey(prntId);
				CbHldr prntHldr = getHldr(prntRec.getBillId(), prntRec.getHldrLvl().intValue());
				if (hldrId.equals(prntHldr.getHldrId())) {
					setExpXfe(cert, rec, hldr, prntRec, true);
					cert.setCertType("11");
					this.cbCertService.save(cert);
				} else {
					setExpXfe(cert, rec, hldr, prntRec, false);
					cert.setCertType("12");
					this.cbCertService.save(cert);
				}
			}
		}
	}

	private void setExpXfe(CbCert cert, CbRec rec, CbHldr hldr, CbRec prntRec, boolean isRemain) {
		String billId = cert.getBillId();
		String hldrId = hldr.getHldrId();
		String finId = rec.getFinId();
		String xfeDate;
		if (hldrId.equals(finId)) {
			List<String> dctStates = new ArrayList();
			dctStates.add("1");
			dctStates.add("2");
			CbDct dct = this.cbDctService.selectDctByBillIdAndStates(billId, dctStates);
			cert.setEntId(dct.getSellerId());
			cert.setXfeNm(dct.getSellerNm());
			xfeDate = dct.getDctDate();
			cert.setXfeDate(xfeDate);
		} else if (prntRec == null) {
			CbXfe xfe = new CbXfe();
			xfe.setBillId(billId);
			xfe.setXfeState("2");
			xfe = (CbXfe) this.cbXfeService.selectOne(xfe);
			xfeDate = xfe.getXfeDate();
			cert.setXfeDate(xfeDate);
			cert.setXfeNm(xfe.getBuyerNm());
		} else {
			CbXfe xfe = new CbXfe();
			xfe.setPrntId(rec.getPrntId());
			xfe.setXfeState("2");
			List<CbXfe> xfes = this.cbXfeService.selectByEntity(xfe);
			String xfeName;
			if ((xfes != null) && (xfes.size() > 0)) {
				if (isRemain) {
					CbRcv rcv = getRcv(rec.getPrntId());
					xfeName = rcv.getBuyerNm();
				} else {
					xfeName = ((CbXfe) xfes.get(0)).getBuyerNm();
				}
				xfeDate = ((CbXfe) xfes.get(0)).getXfeDate();
			} else {
				CbRcv rcv = getRcv(rec.getPrntId());
				xfeDate = rcv.getRcvDate();
				xfeName = rcv.getBuyerNm();
			}
			cert.setXfeNm(xfeName);
			cert.setXfeDate(xfeDate);
		}
		if (prntRec != null) {
			cert.setPrntCode(prntRec.getBillCode());
			cert.setSplitDate(xfeDate);
		}
	}

	private CbRcv getRcv(String billId) {
		CbRcv rcv = new CbRcv();
		rcv.setBillId(billId);
		rcv.setRcvState("2");
		return (CbRcv) this.cbRcvService.selectOne(rcv);
	}

	private CbCert initExpCert(CbRec rec, CbHldr hldr) {
		CbCert cert = new CbCert();

		cert.setCertId(SystemUtil.getUUID());
		cert.setCertDate(DateUtil.getSystemDate());
		cert.setCreateTime(DateUtil.getSystemDateTime());
		cert.setStateNm("S018");

		initRec(cert, rec);
		initSnd(cert, rec.getRootId());
		initHldr(cert, hldr.getHldrId());
		initFin(cert, rec.getRootId());

		return cert;
	}

	private CbXfe getXfe(CbRec cbRecord, CbRcv cbRcv) {
		if ("1".equals(cbRcv.getTxType())) {
			CbXfe cbXfe = new CbXfe();
			cbXfe.setBillId(cbRecord.getBillId());
			cbXfe.setXfeState("2");
			cbXfe = (CbXfe) this.cbXfeService.selectOne(cbXfe);

			return cbXfe;
		}
		return null;
	}

	private CbHldr getHldr(String billId, int hldrLvl) {
		CbHldr hldr = new CbHldr();
		hldr.setBillId(billId);
		hldr.setHldrLvl(Integer.valueOf(hldrLvl));
		return (CbHldr) this.cbHldrService.selectOne(hldr);
	}
}
